<template>
    <Teleport to="body">
      <!-- 抽屉动画包裹 -->
      <Transition name="slide-right">
        <div v-show="modelValue" class="drawer-wrapper">
          <!-- 抽屉内容 -->
          <div class="drawer" :style="{ width: currentWidth + 'px' }">
            <!-- 插槽内容 -->
            <slot></slot>
          </div>
  
          <!-- 拖拽条 -->
          <div class="resizer" @mousedown="startResizing"></div>
        </div>
      </Transition>
  
      <!-- 遮罩层 -->
      <Transition name="fade">
        <div
          v-show="modelValue && maskClosable"
          class="overlay"
          @click="handleMaskClick"
        ></div>
      </Transition>
    </Teleport>
  </template>
  
  <script setup>
  import { ref, computed, watch } from 'vue'
  
  const props = defineProps({
    modelValue: {
      type: Boolean,
      default: false
    },
    initialWidth: {
      type: Number,
      default: 300
    },
    minWidth: {
      type: Number,
      default: 150
    },
    maxWidth: {
      type: Number,
      default: undefined // 默认 undefined 表示全屏
    },
    maskClosable: {
      type: Boolean,
      default: true
    }
  })
  
  const emit = defineEmits(['update:modelValue', 'resize', 'halfScreenWidth', 'lessThanHalfScreenWidth'])
  
  // 当前抽屉宽度
  const currentWidth = ref(props.initialWidth)
  
  // 是否正在拖动
  const isResizing = ref(false)
  
  // 是否已经触发过“达到50%”或“小于50%”
  const isOverHalf = ref(false)
  
  // 实际最大宽度：如果未传 maxWidth，则使用 window.innerWidth
  const effectiveMaxWidth = computed(() => {
    return typeof props.maxWidth === 'number' ? props.maxWidth : window.innerWidth
  })
  
  // 屏幕宽度的 50%
  const halfScreenWidth = computed(() => window.innerWidth * 0.5)
  
  // 同步初始宽度
  watch(
    () => props.initialWidth,
    (val) => {
      currentWidth.value = val
    }
  )
  
  // 切换显示状态
  const toggleDrawer = (val) => {
    emit('update:modelValue', val)
  }
  
  // 点击遮罩关闭
  const handleMaskClick = () => {
    if (props.maskClosable) {
      toggleDrawer(false)
    }
  }
  
  // 开始拖动
  const startResizing = (e) => {
    isResizing.value = true
    document.addEventListener('mousemove', handleMouseMove)
    document.addEventListener('mouseup', stopResizing)
    e.preventDefault()
  }
  
  // 拖动中
  const handleMouseMove = (e) => {
    if (!isResizing.value) return
  
    let newWidth = window.innerWidth - e.clientX
  
    if (newWidth >= props.minWidth && newWidth <= effectiveMaxWidth.value) {
      currentWidth.value = newWidth
      emit('resize', newWidth)
  
      // 判断是否越过 50% 的边界
      if (!isOverHalf.value && newWidth >= halfScreenWidth.value) {
        emit('halfScreenWidth')
        isOverHalf.value = true
      } else if (isOverHalf.value && newWidth < halfScreenWidth.value) {
        emit('lessThanHalfScreenWidth')
        isOverHalf.value = false
      }
    }
  }
  
  // 停止拖动
  const stopResizing = () => {
    isResizing.value = false
    document.removeEventListener('mousemove', handleMouseMove)
    document.removeEventListener('mouseup', stopResizing)
  }
  </script>
  
  <style lang="less" scoped>
  .drawer-wrapper {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    height: 100vh;
    display: flex;
    z-index: 999;
  }
  
  .drawer {
    background-color: #fff;
    border-left: 1px solid #ddd;
    box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
    height: 100vh;
    padding: 20px;
    box-sizing: border-box;
    overflow-y: auto;
    z-index: 1000;
  }
  
  .resizer {
    width: 10px;
    cursor: ew-resize;
    background-color: transparent;
    position: absolute;
    left: -5px;
    top: 0;
    bottom: 0;
    z-index: 1001;
  }
  
  .overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.3);
    z-index: 998;
  }
  
  /* 动画 */
  .slide-right-enter-active,
  .slide-right-leave-active {
    transition: transform 0.3s ease;
  }
  .slide-right-enter-from,
  .slide-right-leave-to {
    transform: translateX(100%);
  }
  
  .fade-enter-active,
  .fade-leave-active {
    transition: opacity 0.3s ease;
  }
  .fade-enter-from,
  .fade-leave-to {
    opacity: 0;
  }
  </style>